package com.nidu.demo.user.gatewayimpl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nidu.demo.user.convertor.UserRoleConvertor;
import com.nidu.demo.user.gateway.UserRoleGateway;
import com.nidu.demo.user.mapper.UserRoleMapper;
import com.nidu.demo.user.mapper.dataobject.UserRoleDO;
import com.nidu.demo.user.model.UserRole;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class UserRoleGatewayImpl implements UserRoleGateway {

    private final UserRoleMapper mapper;

    private final UserRoleConvertor convertor;

    @Override
    public void bindUserRoles(Long userId, Set<Long> roleIds) {
        List<UserRole> bindings = roleIds.stream()
                .map(roleId -> UserRole.create(userId, roleId))
                .collect(Collectors.toList());
        mapper.insert(convertor.toDataObjects(bindings));
    }

    @Override
    public void rebindUserRoles(Long userId, Set<Long> roleIds) {
        removeUserRoles(userId);
        bindUserRoles(userId, roleIds);
    }

    @Override
    public void removeUserRoles(Long userId) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleDO::getUserId, userId);
        mapper.delete(wrapper);
    }

    @Override
    public void removeRoleUsers(Long roleId) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleDO::getRoleId, roleId);
        mapper.delete(wrapper);
    }

    @Override
    public void removeUsersRoles(Set<Long> userIds) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserRoleDO::getUserId, userIds);
        mapper.delete(wrapper);
    }

    @Override
    public void removeRolesUsers(Set<Long> roleIds) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserRoleDO::getRoleId, roleIds);
        mapper.delete(wrapper);
    }

    @Override
    public Set<Long> getRoleIdsByUserId(Long userId) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleDO::getUserId, userId);
        List<UserRoleDO> userRoleDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(userRoleDOS)) {
            return new HashSet<>();
        }
        return userRoleDOS.stream().map(UserRoleDO::getRoleId).collect(Collectors.toSet());
    }

    @Override
    public Set<Long> getUserIdsByRoleId(Long roleId) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleDO::getRoleId, roleId);
        List<UserRoleDO> userRoleDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(userRoleDOS)) {
            return new HashSet<>();
        }
        return userRoleDOS.stream().map(UserRoleDO::getUserId).collect(Collectors.toSet());
    }

    @Override
    public Map<Long, List<UserRole>> getByUserIds(Set<Long> userIds) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserRoleDO::getUserId, userIds);
        List<UserRoleDO> roleDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(roleDOS)) {
            return Collections.emptyMap();
        }
        List<UserRole> userRoles = convertor.toDomainObjects(roleDOS);
        return userRoles.stream().collect(Collectors.groupingBy(UserRole::getUserId));
    }

    @Override
    public Map<Long, List<UserRole>> getByRoleIds(Set<Long> roleIds) {
        LambdaQueryWrapper<UserRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserRoleDO::getRoleId, roleIds);
        List<UserRoleDO> roleDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(roleDOS)) {
            return Collections.emptyMap();
        }
        List<UserRole> userRoles = convertor.toDomainObjects(roleDOS);
        return userRoles.stream().collect(Collectors.groupingBy(UserRole::getUserId));
    }
}